package pl.bristleback.server.bristle.config;

import org.apache.log4j.Logger;
import pl.bristleback.server.bristle.exceptions.handlers.ActionExceptionType;
import pl.bristleback.server.bristle.exceptions.handlers.ExceptionHandler;
import pl.bristleback.server.bristle.exceptions.handlers.ExceptionHandlersContainer;

import java.util.List;
import java.util.Map;

/**
 * This class loads exception handlers using plugin settings taken from configuration file.
 * Exception handlers may be Spring refs or simple instances created by plugin.
 * <p/>
 * Created on: 2010-10-24 00:26:35 <br/>
 *
 * @author Wojciech Niemiec
 */
public final class ExceptionHandlersInitializer {
  private static Logger log = Logger.getLogger(ExceptionHandlersInitializer.class.getName());

  private ExceptionHandlersContainer exceptionHandlersContainer;

  /**
   * Loads exception handlers and stores results in exception handlers container.
   *
   * @param pluginSettings map of plugin settings taken from configuration file.
   */
  public void loadExceptionsHandlers(Map<String, Object> pluginSettings) {
    exceptionHandlersContainer = new ExceptionHandlersContainer();
    List<ClassConfiguration> exceptionHandlerConfigurationsList = getHandlersInformationList(pluginSettings);
    for (ClassConfiguration exceptionHandlerConfiguration : exceptionHandlerConfigurationsList) {
      addHandler(exceptionHandlerConfiguration);
    }
  }

  private void addHandler(ClassConfiguration exceptionHandlerConfiguration) {
    ActionExceptionType actionExceptionType = getExceptionType(exceptionHandlerConfiguration.getName());
    if (actionExceptionType != null) {
      ExceptionHandler exceptionHandler = getExceptionHandler(exceptionHandlerConfiguration);
      exceptionHandlersContainer.addHandler(actionExceptionType, exceptionHandler);
    }
  }

  private ActionExceptionType getExceptionType(String exceptionTypeName) {
    try {
      return ActionExceptionType.valueOf(exceptionTypeName);
    } catch (Exception e) {
      return null;
    }
  }

  private ExceptionHandler getExceptionHandler(ClassConfiguration exceptionHandlerConfiguration) {
    return ClassConfigurationUtil.getInstanceFromConfiguration(ExceptionHandler.class, exceptionHandlerConfiguration);
  }

  private List<ClassConfiguration> getHandlersInformationList(Map<String, Object> pluginSettings) {
    return ClassConfigurationUtil
      .getClassConfigurationsFromSettingsMap(BristleConstants.EXCEPTION_HANDLER_SETTING_KEY_PREFIX, pluginSettings);
  }

  /**
   * Gets exception handlers container. Container must be loaded before by invoking
   * {@link pl.bristleback.server.bristle.config.ExceptionHandlersInitializer#loadExceptionsHandlers(java.util.Map)} method.
   *
   * @return exception handlers container.
   */
  public ExceptionHandlersContainer getExceptionHandlersContainer() {
    return exceptionHandlersContainer;
  }
}
